/**
* @file image_processor_v200.cpp
*
* Copyright (C) Huawei Technologies Co., Ltd. 2019-2020. All Rights Reserved.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "image_processor_v200.h"

#include <set>
#include <memory>
#include "securec.h"
#include "common/log_inner.h"
#include "error_codes_inner.h"
#include "aicpu/dvpp/dvpp_def.h"
#include "aicpu/common/aicpu_task_struct.h"
#include "single_op/dvpp/common/dvpp_util.h"
#include "utils/math_utils.h"

namespace {
    // 3 interplation type(value: 0 default Bilinear/1 Bilinear/2 Nearest neighbor)
    constexpr uint32_t DVPP_RESIZE_INTERPLATION_TYPE_UPPER = 2U;
    constexpr uint16_t LUT_MAP_DEFAULT_VALUE = 256U;
    constexpr uint16_t HIST_DEFAULT_LENGTH = 256U;
    constexpr uint32_t JPEGE_MAX_WIDTH = 8192U;
    constexpr uint32_t JPEGE_MAX_HEIGHT = 8192U;

    aclError CheckBatchAndBorderCfg(const acldvppBatchPicDesc *const dstBatchPicDescs,
        acldvppBorderConfig *borderCfgs[], const uint32_t totalBorderNums)
    {
        const uint32_t MAX_VPC_OUTPUT_RESOLUTION = 4096U;
        for (uint32_t idx = 0U; idx < dstBatchPicDescs->dvppBatchPicDescs.batchSize; ++idx) {
            const uint32_t height = dstBatchPicDescs->aclDvppPicDescs[idx].dvppPicDesc.height;
            if (height > MAX_VPC_OUTPUT_RESOLUTION) {
                ACL_LOG_ERROR("[Check][HEIGHT]dstBatchPicDescs height [%u] can not be larger than %u, index is %u",
                    height, MAX_VPC_OUTPUT_RESOLUTION, idx);
                const std::string convertedStr = std::to_string(height);
                const std::string errMsg =
                    acl::AclErrorLogManager::FormatStr("can not be larger than %u", MAX_VPC_OUTPUT_RESOLUTION);
                const char_t *argList[] = {"param", "value", "reason"};
                const char_t *argVal[] = {"dstBatchPicDescs height", convertedStr.c_str(), errMsg.c_str()};
                acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                    argList, argVal, 3U);
                return ACL_ERROR_INVALID_PARAM;
            }
            const uint32_t width = dstBatchPicDescs->aclDvppPicDescs[idx].dvppPicDesc.width;
            if (width > MAX_VPC_OUTPUT_RESOLUTION) {
                ACL_LOG_ERROR("[Check][WIDTH]dstBatchPicDescs width [%u] can not be larger than %u, index is %u",
                    width, MAX_VPC_OUTPUT_RESOLUTION, idx);
                const std::string convertedStr = std::to_string(width);
                const std::string errMsg =
                    acl::AclErrorLogManager::FormatStr("can not be larger than %u", MAX_VPC_OUTPUT_RESOLUTION);
                const char_t *argList[] = {"param", "value", "reason"};
                const char_t *argVal[] = {"dstBatchPicDescs width", convertedStr.c_str(), errMsg.c_str()};
                acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                    argList, argVal, 3U);
                return ACL_ERROR_INVALID_PARAM;
            }
        }
        for (uint32_t i = 0U; i < totalBorderNums; ++i) {
            ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(borderCfgs[i]);
            const uint32_t borderTypeTmp = borderCfgs[i]->dvppBorderConfig.borderType;
            if ((borderTypeTmp != static_cast<uint32_t>(BORDER_CONSTANT)) &&
                (borderTypeTmp != static_cast<uint32_t>(BORDER_REPLICATE))) {
                ACL_LOG_ERROR("[Check][BORDERTYPE] borderType [%u] is invalid, "
                    "only supported BORDER_CONSTANT and BORDER_REPLICATE", borderTypeTmp);
                const std::string convertedStr = std::to_string(borderTypeTmp);
                const std::string errMsg =
                    acl::AclErrorLogManager::FormatStr("only supported BORDER_CONSTANT and BORDER_REPLICATE");
                const char_t *argList[] = {"param", "value", "reason"};
                const char_t *argVal[] = {"borderType", convertedStr.c_str(), errMsg.c_str()};
                acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                    argList, argVal, 3U);
                return ACL_ERROR_INVALID_PARAM;
            }
        }
        return ACL_SUCCESS;
    }
}

namespace acl {
    namespace dvpp {
    aclError ImageProcessorV200::acldvppVpcConvertColorAsync(acldvppChannelDesc *const channelDesc,
                                                             acldvppPicDesc *const inputDesc,
                                                             acldvppPicDesc *const outputDesc,
                                                             const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppVpcConvertColorAsync");
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->notify);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(inputDesc);
        ACL_REQUIRES_NOT_NULL(inputDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(outputDesc);
        ACL_REQUIRES_NOT_NULL(outputDesc->dataBuffer.data);

        // check convert color param
        const aclError validConvertColorRet = ValidConvertColorParam(inputDesc, outputDesc);
        if (validConvertColorRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Validate][ConvertColorParam]verify convert color param failed, "
                "result = %d.", validConvertColorRet);
            return validConvertColorRet;
        }

        // ConvertColor have 3 inputs
        constexpr uint32_t ioAddrNum = 3U;
        constexpr size_t argsSize = sizeof(aicpu::AicpuParamHead) +
            (ioAddrNum * sizeof(uint64_t));
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = static_cast<uint32_t>(argsSize);
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddress = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        ioAddress[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ioAddress[1] = reinterpret_cast<uintptr_t>(inputDesc->dataBuffer.data);
        ioAddress[2] = reinterpret_cast<uintptr_t>(outputDesc->dataBuffer.data);

        aclError cpyPicRet = ACL_SUCCESS;
        if (aclRunMode_ == ACL_HOST) {
            cpyPicRet = CopyDvppPicDescAsync(inputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (cpyPicRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy convert color input pic desc failed, errorCode = %d.",
                    cpyPicRet);
                return cpyPicRet;
            }
            cpyPicRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (cpyPicRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy convert color output pic desc failed, "
                    "result = %d.", cpyPicRet);
                return cpyPicRet;
            }
        }

        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), argsSize,
            acl::dvpp::DVPP_KERNELNAME_CONVERT_COLOR, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            cpyPicRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_DEVICE_TO_HOST, stream);
            if (cpyPicRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy convert color output pic desc from device failed, "
                    "runtime errorCode = %d.", cpyPicRet);
                return cpyPicRet;
            }
        }

        ACL_LOG_INFO("end to execute acldvppVpcConvertColorAsync");
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::acldvppVpcPyrDownAsync(acldvppChannelDesc *const channelDesc,
                                                        acldvppPicDesc *const inputDesc,
                                                        acldvppPicDesc *const outputDesc,
                                                        void *const reserve,
                                                        const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppVpcPyrDownAsync");
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->notify);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(inputDesc);
        ACL_REQUIRES_NOT_NULL(inputDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(outputDesc);
        ACL_REQUIRES_NOT_NULL(outputDesc->dataBuffer.data);
        if (reserve != nullptr) {
            ACL_LOG_ERROR("[Check][Reserve]paramete reserve must be null.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"reserve"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                argList, argVal, 1U);
            return ACL_ERROR_INVALID_PARAM;
        }

        const aclError validPyrDownInputRet = ValidatePyrDownFormat(
            static_cast<acldvppPixelFormat>(inputDesc->dvppPicDesc.format));
        if (validPyrDownInputRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Check][PyrDownFormat]input acldvppPicDesc format verify failed, errorCode = %d, "
                "format = %u.", validPyrDownInputRet, inputDesc->dvppPicDesc.format);
            return validPyrDownInputRet;
        }

        const aclError validPyrDownOutputRet = ValidatePyrDownFormat(
            static_cast<acldvppPixelFormat>(outputDesc->dvppPicDesc.format));
        if (validPyrDownOutputRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Check][PyrDownFormat]output acldvppPicDesc format verify failed, "
                "result = %d, format = %u.", validPyrDownOutputRet, outputDesc->dvppPicDesc.format);
            return validPyrDownOutputRet;
        }

        // PyrDown have 3 inputs
        constexpr uint32_t ioAddrNum = 3U;
        constexpr size_t argsSize = sizeof(aicpu::AicpuParamHead) +
            (ioAddrNum * sizeof(uint64_t));
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = static_cast<uint32_t>(argsSize);
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ioAddr[1] = reinterpret_cast<uintptr_t>(inputDesc->dataBuffer.data);
        ioAddr[2] = reinterpret_cast<uintptr_t>(outputDesc->dataBuffer.data);

        if (aclRunMode_ == ACL_HOST) {
            aclError cpyRet = CopyDvppPicDescAsync(inputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy input pic desc failed, errorCode = %d.", cpyRet);
                return cpyRet;
            }
            cpyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy output pic desc to device failed, errorCode = %d.", cpyRet);
                return cpyRet;
            }
        }

        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), argsSize,
            acl::dvpp::DVPP_KERNELNAME_PYR_DOWN, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            const auto cpyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_DEVICE_TO_HOST, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy output pic desc from device failed, errorCode = %d.", cpyRet);
                return cpyRet;
            }
        }

        ACL_LOG_INFO("end to execute acldvppVpcPyrDownAsync");
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::acldvppVpcEqualizeHistAsync(const acldvppChannelDesc *const channelDesc,
                                                             const acldvppPicDesc *const inputDesc,
                                                             acldvppPicDesc *const outputDesc,
                                                             const acldvppLutMap *const lutMap,
                                                             const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppVpcEqualizeHistAsync.");
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->notify);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(inputDesc);
        ACL_REQUIRES_NOT_NULL(inputDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(outputDesc);
        ACL_REQUIRES_NOT_NULL(outputDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(lutMap);
        ACL_REQUIRES_NOT_NULL(lutMap->dvppLutMap.map);

        // check param
        const aclError validEqualizeHistRet = ValidEqualizeHistParam(inputDesc, outputDesc);
        if (validEqualizeHistRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Check][EqualizeHist]verify equalize hist param failed, "
                "result = %d.", validEqualizeHistRet);
            return validEqualizeHistRet;
        }

        uint32_t lutMapSize = 0U;
        for (uint32_t idx = 0U; idx < lutMap->dvppLutMap.dims; ++idx) {
            lutMapSize += lutMap->dvppLutMap.lens[idx];
        }
        // EqualizeHist have 3 inputs
        constexpr uint32_t ioAddrNum = 3U;
        const uint32_t cpyLutMapSize = CalDevDvppStructRealUsedSize(&lutMap->dvppLutMap);
        const size_t argsSize = sizeof(aicpu::AicpuParamHead) +
            (ioAddrNum * sizeof(uint64_t)) + cpyLutMapSize + lutMapSize;
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = static_cast<uint32_t>(argsSize);
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddress = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        ioAddress[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ioAddress[1] = reinterpret_cast<uintptr_t>(inputDesc->dataBuffer.data);
        ioAddress[2] = reinterpret_cast<uintptr_t>(outputDesc->dataBuffer.data);
        constexpr size_t headOffset = sizeof(aicpu::AicpuParamHead) +
            (ioAddrNum * sizeof(uint64_t));
        auto memcpyRet = memcpy_s(args.get() + headOffset,
                                  argsSize - headOffset,
                                  &(lutMap->dvppLutMap),
                                  static_cast<size_t>(cpyLutMapSize));
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][lutMap]copy lut map to args failed, result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }
        memcpyRet = memcpy_s(args.get() + headOffset + cpyLutMapSize,
                             argsSize - headOffset - cpyLutMapSize,
                             lutMap->dvppLutMap.map, static_cast<size_t>(lutMapSize));
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][Map]copy map to args failed, result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }

        aclError valCpyRet = ACL_SUCCESS;
        if (aclRunMode_ == ACL_HOST) {
            valCpyRet = CopyDvppPicDescAsync(inputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (valCpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy equalize hist input pic desc failed,\
                    errorCode = %d.", valCpyRet);
                return valCpyRet;
            }
            valCpyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (valCpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy equalize hist output pic desc failed, errorCode = %d.",
                    valCpyRet);
                return valCpyRet;
            }
        }

        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), static_cast<uint32_t>(argsSize),
            acl::dvpp::DVPP_KERNELNAME_EQUALIZE_HIST, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            valCpyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_DEVICE_TO_HOST, stream);
            if (valCpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy equalize hist output pic desc from device failed, "
                    "result = %d.", valCpyRet);
                return valCpyRet;
            }
        }

        ACL_LOG_INFO("end to execute acldvppVpcEqualizeHistAsync");
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::LaunchTaskForVpcBatchCropResizeMakeBorder(const acldvppChannelDesc *const channelDesc,
        const VpcBatchParams &batchParams, const acldvppBorderConfig *const borderCfgs[],
        const acldvppResizeConfig *const resizeConfig, const rtStream_t stream) const
    {
        // check corp area and makeBorderConfigs, batchParams.totalRoiNums_ at least >= 1
        for (uint32_t idx = 0U; idx < batchParams.totalRoiNums_; ++idx) {
            ACL_REQUIRES_NOT_NULL(batchParams.cropAreas_[idx]);
            ACL_REQUIRES_NOT_NULL(borderCfgs[idx]);
        }

        // calculate crop config total size
        const uint32_t cropAreaSize = sizeof(aicpu::dvpp::DvppRoiConfig);
        const uint32_t totalCropConfigSize = cropAreaSize * batchParams.totalRoiNums_;
        const uint32_t resizeConfigSize =  CalDevDvppStructRealUsedSize(&resizeConfig->dvppResizeConfig);
        const uint32_t makeBorderSize = CalDevDvppStructRealUsedSize(&borderCfgs[0]->dvppBorderConfig);
        const uint32_t totalMakeBorderSize = makeBorderSize * batchParams.totalRoiNums_;

        // BatchCrop have 3 inputs
        constexpr uint32_t addrNum = 3U;
        const size_t argsSize = sizeof(aicpu::AicpuParamHead) + (static_cast<uint32_t>(addrNum) * sizeof(uint64_t)) +
            totalCropConfigSize + (batchParams.batchSize_ * sizeof(uint16_t)) + resizeConfigSize + totalMakeBorderSize;
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = static_cast<uint32_t>(argsSize);
        paramHead->ioAddrNum = addrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ioAddr[1] = reinterpret_cast<uintptr_t>(batchParams.srcBatchPicDescs_->dataBuffer.data);
        ioAddr[2] = reinterpret_cast<uintptr_t>(batchParams.dstBatchPicDescs_->dataBuffer.data);

        size_t cropAreaOffset = sizeof(aicpu::AicpuParamHead) + (addrNum * sizeof(uint64_t));
        // copy crop config
        for (size_t idx = 0U; idx < batchParams.totalRoiNums_; ++idx) {
            const auto memcpyRet = memcpy_s(args.get() + cropAreaOffset, argsSize - cropAreaOffset,
                &(batchParams.cropAreas_[idx]->dvppRoiConfig), cropAreaSize);
            if (memcpyRet != EOK) {
                ACL_LOG_INNER_ERROR("[Copy][cropAreas]copy crop area to args failed, result = %d.", memcpyRet);
                return ACL_ERROR_FAILURE;
            }
            cropAreaOffset += cropAreaSize;
        }
        // copy roiNums
        auto memcpyRet = memcpy_s(args.get() + cropAreaOffset, argsSize - cropAreaOffset,
                                  batchParams.roiNums_, sizeof(uint16_t) * batchParams.batchSize_);
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][roiNums]copy roiNums to args failed, result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }

        // copy resize config
        const size_t resizeConfigOffset = cropAreaOffset + (sizeof(uint16_t) * batchParams.batchSize_);
        memcpyRet = memcpy_s(args.get() + resizeConfigOffset, argsSize - resizeConfigOffset,
            &(resizeConfig->dvppResizeConfig), static_cast<size_t>(resizeConfigSize));
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][resizeConfig]copy resize config to args failed, result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }

        size_t borderConfigOffset = resizeConfigOffset + resizeConfigSize;
        // copy makeBorderConfig
        for (size_t idx = 0U; idx < batchParams.totalRoiNums_; ++idx) {
            memcpyRet = memcpy_s(args.get() + borderConfigOffset, argsSize - borderConfigOffset,
                &(borderCfgs[idx]->dvppBorderConfig), static_cast<size_t>(makeBorderSize));
            if (memcpyRet != EOK) {
                ACL_LOG_INNER_ERROR("[Copy][makeborderConfig]copy makeborder config to args failed, "
                    "result = %d.", memcpyRet);
                return ACL_ERROR_FAILURE;
            }
            borderConfigOffset += makeBorderSize;
        }

        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), static_cast<uint32_t>(argsSize),
            acl::dvpp::DVPP_KERNELNAME_BATCH_CROP_RESIZE_MAKEBORDER, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::acldvppVpcBatchCropResizeMakeBorderAsync(acldvppChannelDesc *const channelDesc,
                                                                          acldvppBatchPicDesc *const srcBatchPicDescs,
                                                                          uint32_t *const roiNums,
                                                                          const uint32_t size,
                                                                          acldvppBatchPicDesc *const dstBatchPicDescs,
                                                                          acldvppRoiConfig *cropAreas[],
                                                                          acldvppBorderConfig *borderCfgs[],
                                                                          acldvppResizeConfig *const resizeConfig,
                                                                          const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppVpcBatchCropResizeMakeBorderAsync.");
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(srcBatchPicDescs);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(srcBatchPicDescs->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(dstBatchPicDescs);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(dstBatchPicDescs->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(cropAreas);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(roiNums);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(borderCfgs);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(resizeConfig);
        ACL_REQUIRES_POSITIVE(size);
        ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(channelDesc->notify);

        // valid input param
        const std::unique_ptr<uint16_t[]> roiNumsPtr(new (std::nothrow)uint16_t[size]);
        if (roiNumsPtr == nullptr) {
            ACL_LOG_INNER_ERROR("[Check][roiNumsPtr]create batch crop roiNums pointer failed, "
                "roiNums size = %u.", size);
            return ACL_ERROR_INVALID_PARAM;
        }

        uint32_t totalRoiNums = 0U;
        aclError validParamRet = ValidateAndConvertVpcBatchParams(srcBatchPicDescs, dstBatchPicDescs, roiNums,
            size, roiNumsPtr.get(), totalRoiNums, BATCH_ROI_MAX_SIZE, resizeConfig);
        if (validParamRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Check][BatchParams]verify batch crop param failed, errorCode = %d.", validParamRet);
            return validParamRet;
        }
        validParamRet = CheckBatchAndBorderCfg(dstBatchPicDescs, borderCfgs, totalRoiNums);
        if (validParamRet != ACL_SUCCESS) {
            return validParamRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            // copy input batch pic desc data
            aclError cpyAsyncRet = CopyDvppBatchPicDescAsync(srcBatchPicDescs, ACL_MEMCPY_HOST_TO_DEVICE, size, stream);
            if (cpyAsyncRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][BatchPicDesc]async copy input batch pic desc to device failed, "
                    "result = %d.", cpyAsyncRet);
                return cpyAsyncRet;
            }

            // copy output batch pic desc data
            cpyAsyncRet = CopyDvppBatchPicDescAsync(dstBatchPicDescs, ACL_MEMCPY_HOST_TO_DEVICE, totalRoiNums, stream);
            if (cpyAsyncRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][BatchPicDesc]async copy output batch pic desc to device failed, "
                    "result = %d.", cpyAsyncRet);
                return cpyAsyncRet;
            }
        } else {
            // set data buffer for input batch pic desc
            aclError setDataRet = SetDataBufferForBatchPicDesc(srcBatchPicDescs, size);
            if (setDataRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Set][DataBuffer]dvpp batch crop set data buffer for src batch pic desc "
                    "failed, errorCode = %d.", setDataRet);
                return setDataRet;
            }

            setDataRet = SetDataBufferForBatchPicDesc(dstBatchPicDescs, totalRoiNums);
            if (setDataRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Set][DataBuffer]dvpp batch crop set data buffer for dst batch "
                    "pic desc failed, errorCode = %d.", setDataRet);
                return setDataRet;
            }
        }

        void *const roiNumsAddress = static_cast<void *>(roiNumsPtr.get());
        const VpcBatchParams batchParams = {srcBatchPicDescs, dstBatchPicDescs, cropAreas, nullptr, totalRoiNums,
            roiNumsAddress, size};

        // launch task
        const aclError launchTaskRet = LaunchTaskForVpcBatchCropResizeMakeBorder(channelDesc, batchParams,
            borderCfgs, resizeConfig, stream);
        if (launchTaskRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch task for vpc batch crop, resize and borders "
                "config failed, errorCode = %d.", launchTaskRet);
            return launchTaskRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            // copy output data
            const aclError validCpyRet = CopyDvppBatchPicDescAsync(dstBatchPicDescs, ACL_MEMCPY_DEVICE_TO_HOST,
                totalRoiNums, stream);
            if (validCpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][BatchPicDesc]copy output batch pic desc to host failed, "
                    "result = %d.", validCpyRet);
                return validCpyRet;
            }
        }

        ACL_LOG_INFO("Launch vpc batch crop, resize and make borders tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::acldvppVpcMakeBorderAsync(const acldvppChannelDesc *const channelDesc,
                                                           const acldvppPicDesc *const inputDesc,
                                                           acldvppPicDesc *const outputDesc,
                                                           const acldvppBorderConfig *const borderConfig,
                                                           const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppVpcMakeBorderAsync.");
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->notify);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(inputDesc);
        ACL_REQUIRES_NOT_NULL(inputDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(outputDesc);
        ACL_REQUIRES_NOT_NULL(outputDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(borderConfig);

        // check param
        aclError validFormatRet = ValidateMakeBorderInputFormat(
            static_cast<acldvppPixelFormat>(inputDesc->dvppPicDesc.format));
        if (validFormatRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Validate][MakeBorderInputFormat]verify make border input picture "
                "format failed, format = %u, errorCode = %d.", inputDesc->dvppPicDesc.format, validFormatRet);
            return validFormatRet;
        }
        validFormatRet = ValidateMakeBorderOutputFormat(
            static_cast<acldvppPixelFormat>(outputDesc->dvppPicDesc.format));
        if (validFormatRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Check][MakeBorderOutputFormat]verify make border output picture "
                "format failed, format = %u, errorCode = %d.", outputDesc->dvppPicDesc.format, validFormatRet);
            return validFormatRet;
        }
        // MakeBorder have 3 inputs
        constexpr uint32_t ioAddrNum = 3U;
        const uint32_t cpyMakeBorderSize = CalDevDvppStructRealUsedSize(&borderConfig->dvppBorderConfig);
        const size_t argsSize = sizeof(aicpu::AicpuParamHead) +
            (ioAddrNum * sizeof(uint64_t)) + cpyMakeBorderSize;
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = static_cast<uint32_t>(argsSize);
        paramHead->ioAddrNum = ioAddrNum;
        const auto address = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        address[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        address[1] = reinterpret_cast<uintptr_t>(inputDesc->dataBuffer.data);
        address[2] = reinterpret_cast<uintptr_t>(outputDesc->dataBuffer.data);
        constexpr size_t headOffset = sizeof(aicpu::AicpuParamHead) +
            (ioAddrNum * sizeof(uint64_t));
        const auto memcpyRet = memcpy_s(args.get() + headOffset,
                                        argsSize - headOffset,
                                        &(borderConfig->dvppBorderConfig),
                                        static_cast<size_t>(cpyMakeBorderSize));
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][MakeBorderConfig]copy make border config to args failed, "
                "result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }

        aclError valCpyRet = ACL_SUCCESS;
        if (aclRunMode_ == ACL_HOST) {
            valCpyRet = CopyDvppPicDescAsync(inputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (valCpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy make border input pic desc failed,\
                    errorCode = %d.", valCpyRet);
                return valCpyRet;
            }
            valCpyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (valCpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy make border output pic desc failed,\
                    errorCode = %d.", valCpyRet);
                return valCpyRet;
            }
        }

        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), static_cast<uint32_t>(argsSize),
            acl::dvpp::DVPP_KERNELNAME_MAKE_BORDER, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            valCpyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_DEVICE_TO_HOST, stream);
            if (valCpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy make border output pic desc from device "
                    "failed, errorCode = %d.", valCpyRet);
                return valCpyRet;
            }
        }

        ACL_LOG_INFO("end to execute acldvppVpcMakeBorderAsync");
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::acldvppVpcCalcHistAsync(acldvppChannelDesc *const channelDesc,
                                                         acldvppPicDesc *const srcPicDesc,
                                                         acldvppHist *const hist,
                                                         void *const reserve,
                                                         const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppVpcCalcHistAsync");
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->notify);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(srcPicDesc);
        ACL_REQUIRES_NOT_NULL(srcPicDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(hist);
        ACL_REQUIRES_NOT_NULL(hist->dvppHistDesc.hist);
        ACL_REQUIRES_NOT_NULL(hist->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(hist->shareBuffer.data);

        if (reserve != nullptr) {
            ACL_LOG_INNER_ERROR("[Check][Reserve]reserve param must be null, but addr = %p.", reserve);
            return ACL_ERROR_INVALID_PARAM;
        }

        uint32_t histSize = 0U;
        for (uint32_t i = 0U; i < hist->dvppHistDesc.dims; ++i) {
            histSize += hist->dvppHistDesc.lens[i];
        }
        const auto histLen = histSize * sizeof(uint32_t);
        if (histLen != hist->shareBuffer.length) {
            ACL_LOG_INNER_ERROR("[Check][HistLen]the length of shareBuffer[%lu] must be equal to hist data size[%lu]",
                hist->shareBuffer.length, histLen);
            return ACL_ERROR_INVALID_PARAM;
        }
        const aclError validVpcInputRet = ValidateCalcHistFormat(
            static_cast<acldvppPixelFormat>(srcPicDesc->dvppPicDesc.format));
        if (validVpcInputRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Check][Input]input acldvppPicDesc format verify failed, errorCode = %d,\
                format = %u.", validVpcInputRet, srcPicDesc->dvppPicDesc.format);
            return validVpcInputRet;
        }

        // CalcHist have 4 inputs
        constexpr uint32_t ioAddrNum = 4U;
        constexpr size_t argsSize = sizeof(aicpu::AicpuParamHead) +
            (ioAddrNum * sizeof(uint64_t));
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = static_cast<uint32_t>(argsSize);
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ioAddr[1] = reinterpret_cast<uintptr_t>(srcPicDesc->dataBuffer.data);
        ioAddr[2] = reinterpret_cast<uintptr_t>(hist->dataBuffer.data);
        ioAddr[3] = reinterpret_cast<uintptr_t>(hist->shareBuffer.data);

        if (aclRunMode_ == ACL_HOST) {
            aclError cpyRet = CopyDvppPicDescAsync(srcPicDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][DvppPicDesc]copy src pic desc failed, errorCode = %d.", cpyRet);
                return cpyRet;
            }

            cpyRet = CopyDvppHistDescAsync(hist, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][DvppHistDesc]copy output hist desc to device failed,\
                    errorCode = %d.", cpyRet);
                return cpyRet;
            }
        }

        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), argsSize,
            acl::dvpp::DVPP_KERNELNAME_CALC_HIST, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            auto cpyRet = CopyDvppHistDescAsync(hist, ACL_MEMCPY_DEVICE_TO_HOST, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][HistDesc]copy output hist desc from device failed,\
                    errorCode = %d.", cpyRet);
                return cpyRet;
            }

            cpyRet = aclrtMemcpyAsync(hist->dvppHistDesc.hist, hist->shareBuffer.length,
                                      hist->shareBuffer.data, histLen,
                                      ACL_MEMCPY_DEVICE_TO_HOST, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][Mem]copy output hist data from device failed, errorCode = %d.", cpyRet);
                return cpyRet;
            }
        }

        ACL_LOG_INFO("end to execute acldvppVpcCalcHistAsync");
        return ACL_SUCCESS;
    }

    acldvppHist* ImageProcessorV200::acldvppCreateHist() const
    {
        acldvppHist *aclHist = nullptr;
        switch (aclRunMode_) {
            case ACL_HOST: {
                aclHist = CreateHistOnHost();
                break;
            }
            case ACL_DEVICE: {
                aclHist = CreateHistOnDevice();
                break;
            }
            default: {
                ACL_LOG_INNER_ERROR("[Run][Mode]unknown acl run mode %d.", aclRunMode_);
                return nullptr;
            }
        }

        if (aclHist == nullptr) {
            ACL_LOG_INNER_ERROR("[Check][Hist]create hist is failed, hist address = %p.", aclHist);
            return nullptr;
        }
        ACL_LOG_INFO("hist data host address = %p.", aclHist->dvppHistDesc.hist);
        ACL_LOG_INFO("hist data device address = %p.", aclHist->shareBuffer.data);
        return aclHist;
    }

    acldvppHist *ImageProcessorV200::CreateHistOnHost() const
    {
        acldvppHist *aclHist = nullptr;
        // alloc host memory
        const uint32_t aclHistSize = CalAclDvppStructSize(aclHist);
        char_t *hostAddr = new (std::nothrow)char_t[aclHistSize];
        if (hostAddr == nullptr) {
            ACL_LOG_INNER_ERROR("[Check][HostAddr]apply host memory for acldvppHist failed. size = %u.", aclHistSize);
            return nullptr;
        }

        // create acldvppHist in host addr
        aclHist = new (hostAddr)acldvppHist;
        if (aclHist == nullptr) {
            ACL_LOG_INNER_ERROR("[Create][Hist]create acldvppHist with function new failed");
            ACL_DELETE_ARRAY_AND_SET_NULL(hostAddr);
            return nullptr;
        }

        // malloc device memory for dvppHistDesc
        void *devPtr = nullptr;
        const size_t devSize = CalDevDvppStructRealUsedSize(&aclHist->dvppHistDesc);
        const uint32_t flags = RT_MEMORY_DEFAULT | RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY;
        rtError_t rtErr = rtMalloc(&devPtr, devSize, flags);
        if (rtErr != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Malloc][Mem]malloc device memory for acl dvpp pic desc failed, size = %zu, "
                "runtime errorCode = %d", devSize, rtErr);
            aclHist->~acldvppHist();
            ACL_DELETE_ARRAY_AND_SET_NULL(hostAddr);
            return nullptr;
        }
        aclHist->dataBuffer.data = devPtr;
        aclHist->dataBuffer.length = devSize;

        // set lens for each dim
        uint32_t histSize = 0U;
        for (uint32_t i = 0U; i < aclHist->dvppHistDesc.dims; ++i) {
            aclHist->dvppHistDesc.lens[i] = HIST_DEFAULT_LENGTH;
            histSize += aclHist->dvppHistDesc.lens[i];
        }
        const auto histLen = histSize * sizeof(uint32_t);

        // malloc device memory for hist data
        void *histData = nullptr;
        rtErr = rtDvppMalloc(&histData, histLen);
        if (rtErr != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Malloc][Mem]malloc device memory for acl dvpp hist data failed, "
                "size = %zu, runtime errorCode = %d", histLen, rtErr);
            aclHist->~acldvppHist();
            (void)rtFree(devPtr);
            devPtr = nullptr;
            ACL_DELETE_ARRAY_AND_SET_NULL(hostAddr);
            return nullptr;
        }
        aclHist->shareBuffer.data = histData;
        aclHist->shareBuffer.length = histLen;

        // apply host memory for hist data
        if (histSize == 0U) {
            ACL_LOG_INNER_ERROR("[Check][HistSize]histSize must be positive, histSize = %u.", histSize);
            aclHist->~acldvppHist();
            (void)rtFree(histData);
            histData = nullptr;
            (void)rtFree(devPtr);
            devPtr = nullptr;
            ACL_DELETE_ARRAY_AND_SET_NULL(hostAddr);
            return nullptr;
        }

        aclHist->dvppHistDesc.hist = new (std::nothrow)uint32_t[histSize];
        if (aclHist->dvppHistDesc.hist == nullptr) {
            ACL_LOG_INNER_ERROR("[Check][HistDesc]create hist data with function new failed on host side.");
            aclHist->~acldvppHist();
            (void)rtFree(histData);
            histData = nullptr;
            (void)rtFree(devPtr);
            devPtr = nullptr;
            ACL_DELETE_ARRAY_AND_SET_NULL(hostAddr);
            return nullptr;
        }

        return aclHist;
    }

    acldvppHist *ImageProcessorV200::CreateHistOnDevice() const
    {
        acldvppHist *aclHist = nullptr;
        // alloc device memory
        void *devAddr = nullptr;
        const uint32_t aclHistSize = CalAclDvppStructSize(aclHist);
        const uint32_t flags = RT_MEMORY_DEFAULT | RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY;
        rtError_t rtErr = rtMalloc(&devAddr, static_cast<uint64_t>(aclHistSize), flags);
        if (rtErr != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Malloc][Mem]malloc device memory failed, size = %u, runtime errorCode = %d",
                aclHistSize, rtErr);
            return nullptr;
        }

        // create acldvppHist in device addr
        aclHist = new (devAddr)acldvppHist;
        if (aclHist == nullptr) {
            ACL_LOG_INNER_ERROR("[Malloc][Hist]create acldvppHist with function new failed");
            (void)rtFree(devAddr);
            devAddr = nullptr;
            return nullptr;
        }

        // set lens for each dim
        uint32_t histSize = 0U;
        for (uint32_t i = 0U; i < aclHist->dvppHistDesc.dims; ++i) {
            aclHist->dvppHistDesc.lens[i] = HIST_DEFAULT_LENGTH;
            histSize += aclHist->dvppHistDesc.lens[i];
        }
        const auto histLen = histSize * sizeof(uint32_t);

        // malloc device memory for hist data
        void *histData = nullptr;
        rtErr = rtDvppMalloc(&histData, histLen);
        if (rtErr != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Malloc][Mem]malloc device memory for acl dvpp hist data failed, size = %zu, "
                "runtime errorCode = %d", histLen, rtErr);
            aclHist->~acldvppHist();
            (void)rtFree(devAddr);
            devAddr = nullptr;
            return nullptr;
        }
        aclHist->shareBuffer.data = histData;
        aclHist->shareBuffer.length = histLen;

        // set data buffer
        aclHist->dvppHistDesc.hist = reinterpret_cast<uint32_t *>(histData);
        const size_t offset = OFFSET_OF_MEMBER(acldvppHist, dvppHistDesc);
        aclHist->dataBuffer.data = reinterpret_cast<aicpu::dvpp::DvppHistDesc *>(
            reinterpret_cast<uintptr_t>(devAddr) + offset);
        aclHist->dataBuffer.length = CalDevDvppStructRealUsedSize(&aclHist->dvppHistDesc);

        return aclHist;
    }

    aclError ImageProcessorV200::acldvppDestroyHist(acldvppHist *const hist) const
    {
        if (hist == nullptr) {
            return ACL_SUCCESS;
        }
        FreeDeviceBuffer(hist->shareBuffer);

        switch (aclRunMode_) {
            case ACL_HOST: {
                FreeDeviceBuffer(hist->dataBuffer);
                ACL_DELETE_ARRAY_AND_SET_NULL(hist->dvppHistDesc.hist);
                hist->~acldvppHist();
                delete[] hist;
                break;
            }
            case ACL_DEVICE: {
                hist->~acldvppHist();
                FreeDeviceAddr(static_cast<void *>(hist));
                break;
            }
            default: {
                ACL_LOG_INNER_ERROR("[Check][Mode]unknown acl run mode %d.", aclRunMode_);
                return ACL_ERROR_INTERNAL_ERROR;
            }
        }

        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::acldvppClearHist(acldvppHist *const hist) const
    {
        if ((hist == nullptr) || (hist->shareBuffer.data == nullptr) || (hist->dvppHistDesc.hist == nullptr)) {
            return ACL_ERROR_INVALID_PARAM;
        }

        uint32_t histSize = 0U;
        for (uint32_t i = 0U; i < hist->dvppHistDesc.dims; ++i) {
            histSize += hist->dvppHistDesc.lens[i];
        }
        const auto histLen = histSize * sizeof(uint32_t);
        if (histLen != hist->shareBuffer.length) {
            ACL_LOG_INNER_ERROR("[Check][histLen]the length of shareBuffer[%zu] must equal to hist data size[%zu]",
                hist->shareBuffer.length, histLen);
            return ACL_ERROR_INVALID_PARAM;
        }

        switch (aclRunMode_) {
            case ACL_HOST: {
                const errno_t err = memset_s(hist->dvppHistDesc.hist, hist->shareBuffer.length, 0, histLen);
                if (err != EOK) {
                    ACL_LOG_INNER_ERROR("[Copy][Mem]set hist data to 0 failed, destMax = %zu, count = %zu.",
                        hist->shareBuffer.length, histLen);
                    return ACL_ERROR_INTERNAL_ERROR;
                }
                break;
            }
            case ACL_DEVICE: {
                const aclError aclRet = aclrtMemset(hist->shareBuffer.data, hist->shareBuffer.length, 0, histLen);
                if (aclRet != ACL_SUCCESS) {
                    ACL_LOG_INNER_ERROR("[Set][Mem]aclrtMemset hist data to 0 fail, destMax = %zu, count = %zu.",
                        hist->shareBuffer.length, histLen);
                    return aclRet;
                }
                break;
            }
            default: {
                ACL_LOG_INNER_ERROR("[Check][RunMode]unknown acl run mode %d.", aclRunMode_);
                return ACL_ERROR_INTERNAL_ERROR;
            }
        }
        return ACL_SUCCESS;
    }

    uint32_t ImageProcessorV200::acldvppGetHistDims(acldvppHist *const hist) const
    {
        if (hist == nullptr) {
            ACL_LOG_ERROR("[Check][Hist]param hist is nullptr");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"hist"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                argList, argVal, 1U);
            return 0U;
        }
        return hist->dvppHistDesc.dims;
    }

    aclError ImageProcessorV200::acldvppGetHistData(acldvppHist *const hist, const uint32_t dim, uint32_t **const data,
        uint16_t *const len) const
    {
        if (hist == nullptr) {
            ACL_LOG_ERROR("[Check][Hist]param hist is nullptr.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"hist"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                argList, argVal, 1U);
            return ACL_ERROR_INVALID_PARAM;
        }
        if (dim >= hist->dvppHistDesc.dims) {
            ACL_LOG_ERROR("[Check][Dim]input dim[%u] should be smaller than hist's dims[%u].",
                dim, hist->dvppHistDesc.dims);
            const std::string dimStr = std::to_string(dim);
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"bufAddr", dimStr.c_str(), "bufAddr is already set"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                argList, argVal, 3U);
            return ACL_ERROR_INVALID_PARAM;
        }
        if (data == nullptr) {
            ACL_LOG_ERROR("[Check][Data]the param of data is nullptr.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"data"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                argList, argVal, 1U);
            return ACL_ERROR_INVALID_PARAM;
        }
        if (len == nullptr) {
            ACL_LOG_ERROR("[Check][Len]the param of len is nullptr.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"len"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                argList, argVal, 1U);
            return ACL_ERROR_INVALID_PARAM;
        }

        uint32_t offset = 0U;
        for (uint32_t i = 0U; i < dim; ++i) {
            offset += hist->dvppHistDesc.lens[i];    // each len default is 256
        }
        *data = hist->dvppHistDesc.hist + offset;
        *len = hist->dvppHistDesc.lens[dim];
        ACL_LOG_INFO("hist data address = %p, len = %u.", *data, static_cast<uint32_t>(*len));
        return ACL_SUCCESS;
    }

    uint32_t ImageProcessorV200::acldvppGetHistRetCode(acldvppHist *const hist) const
    {
        if (hist == nullptr) {
            ACL_LOG_ERROR("[Check][Hist]the param of hist is nullptr.");
            return static_cast<uint32_t>(ACL_ERROR_INVALID_PARAM);
        }
        return hist->dvppHistDesc.retCode;
    }

    aclError ImageProcessorV200::acldvppSetResizeConfigInterpolation(acldvppResizeConfig *const resizeConfig,
                                                                     const uint32_t interpolation)
    {
        ACL_LOG_DEBUG("start to execute acldvppSetResizeConfigInterpolation.");
        ACL_REQUIRES_NOT_NULL(resizeConfig);
        // 3 interplation type(value: 0 default Bilinear/1 Bilinear/2 Nearest neighbor)
        if (interpolation > DVPP_RESIZE_INTERPLATION_TYPE_UPPER) {
            ACL_LOG_ERROR("[Check][Interpolation]the current interpolation[%u] is not support.", interpolation);
            const std::string errMsg = acl::AclErrorLogManager::FormatStr("the current interpolation[%u]",
                interpolation);
            const char_t *argList[] = {"feature", "reason"};
            const char_t *argVal[] = {errMsg.c_str(), "not support"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG, argList, argVal, 2U);
            return ACL_ERROR_INVALID_PARAM;
        }
        resizeConfig->dvppResizeConfig.interpolation = interpolation;
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::acldvppSetChannelDescMode(acldvppChannelDesc *const channelDesc,
                                                           const uint32_t channelMode)
    {
        ACL_LOG_INFO("start to execute acldvppSetChannelDescMode.");
        ACL_REQUIRES_NOT_NULL(channelDesc);
        if ((channelMode > (static_cast<uint32_t>(DVPP_CHNMODE_VPC) | static_cast<uint32_t>(DVPP_CHNMODE_JPEGD) |
            static_cast<uint32_t>(DVPP_CHNMODE_JPEGE) | static_cast<uint32_t>(DVPP_CHNMODE_PNGD))) ||
            (channelMode < DVPP_CHNMODE_VPC)) {
            ACL_LOG_ERROR("[Check][Params]the current mode[%u] is not support", channelMode);
            const std::string errMsg = acl::AclErrorLogManager::FormatStr("the current mode[%u]",
                channelMode);
            const char_t *argList[] = {"feature", "reason"};
            const char_t *argVal[] = {errMsg.c_str(), "not support"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG, argList, argVal, 2U);
            return ACL_ERROR_INVALID_PARAM;
        }
        channelDesc->dvppDesc.channelMode = channelMode;
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::ValidateVpcInputFormat(const acldvppPixelFormat format) const
    {
        static const std::set<acldvppPixelFormat> vpcInputFormatSet = {
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_400,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_422,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_422,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_444,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_444,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_PACKED_444,
            acldvppPixelFormat::PIXEL_FORMAT_YUYV_PACKED_422,
            acldvppPixelFormat::PIXEL_FORMAT_UYVY_PACKED_422,
            acldvppPixelFormat::PIXEL_FORMAT_YVYU_PACKED_422,
            acldvppPixelFormat::PIXEL_FORMAT_VYUY_PACKED_422,
            acldvppPixelFormat::PIXEL_FORMAT_ARGB_8888,
            acldvppPixelFormat::PIXEL_FORMAT_RGB_888,
            acldvppPixelFormat::PIXEL_FORMAT_BGR_888,
            acldvppPixelFormat::PIXEL_FORMAT_ABGR_8888,
            acldvppPixelFormat::PIXEL_FORMAT_RGBA_8888,
            acldvppPixelFormat::PIXEL_FORMAT_BGRA_8888,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_440,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_440
        };

        std::set<acldvppPixelFormat>::const_iterator iter = vpcInputFormatSet.find(format);
        if (iter != vpcInputFormatSet.cend()) {
            return ACL_SUCCESS;
        }
        return ACL_ERROR_FORMAT_NOT_MATCH;
    }

    aclError ImageProcessorV200::ValidateVpcOutputFormat(const acldvppPixelFormat format) const
    {
        static const std::set<acldvppPixelFormat> vpcOutputFormatSet = {
            acldvppPixelFormat::PIXEL_FORMAT_YUV_400,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_422,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_422,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_PACKED_444,
            acldvppPixelFormat::PIXEL_FORMAT_BGR_888,
            acldvppPixelFormat::PIXEL_FORMAT_RGB_888,
            acldvppPixelFormat::PIXEL_FORMAT_ARGB_8888,
            acldvppPixelFormat::PIXEL_FORMAT_ABGR_8888,
            acldvppPixelFormat::PIXEL_FORMAT_RGBA_8888,
            acldvppPixelFormat::PIXEL_FORMAT_BGRA_8888
        };

        std::set<acldvppPixelFormat>::const_iterator iter = vpcOutputFormatSet.find(format);
        if (iter != vpcOutputFormatSet.cend()) {
            return ACL_SUCCESS;
        }
        return ACL_ERROR_FORMAT_NOT_MATCH;
    }

    aclError ImageProcessorV200::ValidateCalcHistFormat(const acldvppPixelFormat format) const
    {
        static const std::set<acldvppPixelFormat> inputFormatSet = {
            acldvppPixelFormat::PIXEL_FORMAT_YUV_400,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_422,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_422,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_444,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_444,
            acldvppPixelFormat::PIXEL_FORMAT_YUYV_PACKED_422,
            acldvppPixelFormat::PIXEL_FORMAT_UYVY_PACKED_422,
            acldvppPixelFormat::PIXEL_FORMAT_YVYU_PACKED_422,
            acldvppPixelFormat::PIXEL_FORMAT_VYUY_PACKED_422,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_PACKED_444,
            acldvppPixelFormat::PIXEL_FORMAT_RGB_888,
            acldvppPixelFormat::PIXEL_FORMAT_BGR_888
        };

        std::set<acldvppPixelFormat>::const_iterator iter = inputFormatSet.find(format);
        if (iter != inputFormatSet.cend()) {
            return ACL_SUCCESS;
        }
        return ACL_ERROR_FORMAT_NOT_MATCH;
    }

    aclError ImageProcessorV200::ValidateDvppResizeConfig(const acldvppResizeConfig *const config) const
    {
        ACL_REQUIRES_NOT_NULL(config);
        // 3 interplation type(value: 0 default Bilinear/1 Bilinear/2 Nearest neighbor)
        if (config->dvppResizeConfig.interpolation > DVPP_RESIZE_INTERPLATION_TYPE_UPPER) {
            ACL_LOG_ERROR("[Check][Interpolation]the current interpolation[%u] is not support",
                config->dvppResizeConfig.interpolation);
            const char_t *argList[] = {"feature", "reason"};
            const char_t *argVal[] = {"interpolation", "interpolation only can be set [0,2]"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG, argList, argVal, 2U);
            return ACL_ERROR_FEATURE_UNSUPPORTED;
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::ValidateConvertColorOutputFormat(const acldvppPixelFormat format) const
    {
        static const std::set<acldvppPixelFormat> cvtColorFormatSet = {
            acldvppPixelFormat::PIXEL_FORMAT_YUV_400,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_422,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_422,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_PACKED_444,
            acldvppPixelFormat::PIXEL_FORMAT_RGB_888,
            acldvppPixelFormat::PIXEL_FORMAT_BGR_888,
            acldvppPixelFormat::PIXEL_FORMAT_ARGB_8888,
            acldvppPixelFormat::PIXEL_FORMAT_ABGR_8888,
            acldvppPixelFormat::PIXEL_FORMAT_RGBA_8888,
            acldvppPixelFormat::PIXEL_FORMAT_BGRA_8888
        };

        std::set<acldvppPixelFormat>::const_iterator iter = cvtColorFormatSet.find(format);
        if (iter != cvtColorFormatSet.cend()) {
            return ACL_SUCCESS;
        }
        return ACL_ERROR_FORMAT_NOT_MATCH;
    }

    aclError ImageProcessorV200::ValidatePyrDownFormat(const acldvppPixelFormat format) const
    {
        static const std::set<acldvppPixelFormat> pyrDownFormatSet = {
            acldvppPixelFormat::PIXEL_FORMAT_YUV_400
        };

        std::set<acldvppPixelFormat>::const_iterator iter = pyrDownFormatSet.find(format);
        if (iter != pyrDownFormatSet.cend()) {
            return ACL_SUCCESS;
        }
        return ACL_ERROR_FORMAT_NOT_MATCH;
    }

    aclError ImageProcessorV200::ValidateEqualizeHistFormat(const acldvppPixelFormat format) const
    {
        static const std::set<acldvppPixelFormat> equalizeHistFormat = {
            acldvppPixelFormat::PIXEL_FORMAT_YUV_400,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_422,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_422,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_PACKED_444,
            acldvppPixelFormat::PIXEL_FORMAT_RGB_888,
            acldvppPixelFormat::PIXEL_FORMAT_BGR_888
        };

        std::set<acldvppPixelFormat>::const_iterator iter = equalizeHistFormat.find(format);
        if (iter != equalizeHistFormat.cend()) {
            return ACL_SUCCESS;
        }
        return ACL_ERROR_FORMAT_NOT_MATCH;
    }

    aclError ImageProcessorV200::ValidateMakeBorderInputFormat(const acldvppPixelFormat format) const
    {
        static const std::set<acldvppPixelFormat> makeBorderFormat = {
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_422,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_422,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_444,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_444,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_PACKED_444,
            acldvppPixelFormat::PIXEL_FORMAT_RGB_888,
            acldvppPixelFormat::PIXEL_FORMAT_BGR_888,
            acldvppPixelFormat::PIXEL_FORMAT_ARGB_8888,
            acldvppPixelFormat::PIXEL_FORMAT_ABGR_8888,
            acldvppPixelFormat::PIXEL_FORMAT_RGBA_8888,
            acldvppPixelFormat::PIXEL_FORMAT_BGRA_8888,
            acldvppPixelFormat::PIXEL_FORMAT_YUYV_PACKED_422,
            acldvppPixelFormat::PIXEL_FORMAT_UYVY_PACKED_422,
            acldvppPixelFormat::PIXEL_FORMAT_YVYU_PACKED_422,
            acldvppPixelFormat::PIXEL_FORMAT_VYUY_PACKED_422,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_440,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_440,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_400
        };

        std::set<acldvppPixelFormat>::const_iterator iter = makeBorderFormat.find(format);
        if (iter != makeBorderFormat.cend()) {
            return ACL_SUCCESS;
        }
        return ACL_ERROR_FORMAT_NOT_MATCH;
    }

    aclError ImageProcessorV200::ValidateMakeBorderOutputFormat(const acldvppPixelFormat format) const
    {
        static const std::set<acldvppPixelFormat> makeBorderFormat = {
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_422,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_422,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_PACKED_444,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_400,
            acldvppPixelFormat::PIXEL_FORMAT_RGB_888,
            acldvppPixelFormat::PIXEL_FORMAT_BGR_888,
            acldvppPixelFormat::PIXEL_FORMAT_RGBA_8888,
            acldvppPixelFormat::PIXEL_FORMAT_BGRA_8888,
            acldvppPixelFormat::PIXEL_FORMAT_ARGB_8888,
            acldvppPixelFormat::PIXEL_FORMAT_ABGR_8888
        };

        std::set<acldvppPixelFormat>::const_iterator iter = makeBorderFormat.find(format);
        if (iter != makeBorderFormat.cend()) {
            return ACL_SUCCESS;
        }
        return ACL_ERROR_FORMAT_NOT_MATCH;
    }

    aclError ImageProcessorV200::ValidConvertColorParam(const acldvppPicDesc *const inputDesc,
                                                        const acldvppPicDesc *const outputDesc) const
    {
        // check vpc input format
        const aclError validConvertColorInputRet = ValidateVpcInputFormat(
            static_cast<acldvppPixelFormat>(inputDesc->dvppPicDesc.format));
        if (validConvertColorInputRet != ACL_SUCCESS) {
            ACL_LOG_ERROR("[Check][ConvertColorInput]input acldvppPicDesc format verify failed, "
                "result = %d, format = %u.", validConvertColorInputRet, inputDesc->dvppPicDesc.format);
            const std::string convertedStr = std::to_string(inputDesc->dvppPicDesc.format);
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"InputFormat", convertedStr.c_str(), "not set in range"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                argList, argVal, 3U);
            return validConvertColorInputRet;
        }
        // check vpc output foramt
        const aclError validConvertColorOutputRet = ValidateConvertColorOutputFormat(
            static_cast<acldvppPixelFormat>(outputDesc->dvppPicDesc.format));
        if (validConvertColorOutputRet != ACL_SUCCESS) {
            ACL_LOG_ERROR("[Check][ConvertColorOutput]output acldvppPicDesc format verify failed, "
                "result = %d, format = %u.", validConvertColorOutputRet, outputDesc->dvppPicDesc.format);
            const std::string convertedStr = std::to_string(outputDesc->dvppPicDesc.format);
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"OutputFormat", convertedStr.c_str(), "not set in range"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                argList, argVal, 3U);
            return validConvertColorOutputRet;
        }

        const uint32_t srcWidth = inputDesc->dvppPicDesc.width;
        const uint32_t srcHeight = inputDesc->dvppPicDesc.height;
        const uint32_t srcWidthStride = inputDesc->dvppPicDesc.widthStride;
        const uint32_t srcHeightStride = inputDesc->dvppPicDesc.heightStride;
        // check source width and height, 0 is invalid value
        bool validPicParam = (srcWidth == 0U) || (srcHeight == 0U) ||
                             (srcWidthStride == 0U) || (srcHeightStride == 0U);
        if (validPicParam) {
            ACL_LOG_ERROR("[Verify][PicParam]verify src picture width and height failed, 0 is invalid value, "
                "width = %u, height = %u, widthStride = %u, heightStride = %u",
                srcWidth, srcHeight, srcWidthStride, srcHeightStride);
            const std::string errMsg = acl::AclErrorLogManager::FormatStr("%u, %u, %u, %u",
                srcWidth, srcHeight, srcWidthStride, srcHeightStride);
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"width, height, widthStride, heightStride",
                errMsg.c_str(), "0 is invalid value"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                argList, argVal, 3U);
            return ACL_ERROR_INVALID_PARAM;
        }
        const uint32_t dstWidth = outputDesc->dvppPicDesc.width;
        const uint32_t dstHeight = outputDesc->dvppPicDesc.height;
        // dst width or height is allowed to be 0
        validPicParam = ((dstWidth != 0U) && (dstWidth != srcWidth)) ||
                        ((dstHeight != 0U) && (dstHeight != srcHeight));
        if (validPicParam) {
            ACL_LOG_ERROR("[Validate][PicParam]convert color dst pic width or height must match "
                "src pic or be 0, srcWidth = %u, "
                "srcHeight = %u, dstWidth = %u, dstHeight = %u", srcWidth, srcHeight, dstWidth, dstHeight);
            const std::string errMsg = acl::AclErrorLogManager::FormatStr("%u, %u, %u, %u",
                srcWidth, srcHeight, srcWidthStride, srcHeightStride);
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"width, height, widthStride, heightStride",
                errMsg.c_str(), "0 is invalid value"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                argList, argVal, 3U);
            return ACL_ERROR_INVALID_PARAM;
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::acldvppGetChannelDescMatrix(const acldvppChannelDesc *const channelDesc,
        acldvppCscMatrix &matrixFormat) const
    {
        ACL_LOG_DEBUG("start to execute acldvppGetChannelDescMatrix");
        if ((channelDesc == nullptr) || (channelDesc->dvppDesc.extendInfo == nullptr)) {
            ACL_LOG_ERROR("[Check][ChannelDesc]channelDesc is null.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"channelDesc or extendInfo"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                argList, argVal, 1U);
            return ACL_ERROR_INVALID_PARAM;
        }
        {
            std::mutex &mutexMap = const_cast<std::mutex &>(channelDesc->mutexForTLVMap);
            const std::unique_lock<std::mutex> lk{mutexMap};
            const auto &it = channelDesc->tlvParamMap.find(DVPP_CSC_MATRIX);
            if (it == channelDesc->tlvParamMap.end()) {
                matrixFormat = ACL_DVPP_CSC_MATRIX_BT601_WIDE;
                return ACL_SUCCESS;
            }

            aicpu::dvpp::DvppCscMatrixConfig *const dvppCscMatrixConfig =
                static_cast<aicpu::dvpp::DvppCscMatrixConfig *>(it->second.value.get());
            if (dvppCscMatrixConfig == nullptr) {
                ACL_LOG_INNER_ERROR("[Check][VencRateControl]vencRateControl ptr is null.");
                return ACL_ERROR_INVALID_PARAM;
            }
            matrixFormat = static_cast<acldvppCscMatrix>(dvppCscMatrixConfig->cscMatrix);
            ACL_LOG_DEBUG("successfully execute aclvdecGetChannelDescMatrix, matrixFormat = %d",
                static_cast<int32_t>(matrixFormat));
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::acldvppSetChannelDescMatrix(acldvppChannelDesc *const channelDesc,
        const acldvppCscMatrix matrixFormat) const
    {
        ACL_LOG_DEBUG("start to execute acldvppSetChannelDescMatrix");
        if ((channelDesc == nullptr) || (channelDesc->dvppDesc.extendInfo == nullptr)) {
            ACL_LOG_ERROR("[Check][ChannelDesc]channelDesc is null.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"channelDesc or extendInfo"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                argList, argVal, 1U);
            return ACL_ERROR_INVALID_PARAM;
        }
        // check if matrix format in range
        if ((matrixFormat < ACL_DVPP_CSC_MATRIX_BT601_WIDE) ||
            (matrixFormat > ACL_DVPP_CSC_MATRIX_BT2020_NARROW)) {
            ACL_LOG_ERROR("[Check][matrixFormat]input format[%u] is not supported in this version",
                static_cast<uint32_t>(matrixFormat));
            const std::string matrixFormatStr = std::to_string(static_cast<uint32_t>(matrixFormat));
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"matrixFormat", matrixFormatStr.c_str(), "not supported in this version"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                argList, argVal, 3U);
            return ACL_ERROR_INVALID_PARAM;
        }

        {
            const std::unique_lock<std::mutex> lk{channelDesc->mutexForTLVMap};
            std::map<acl::DvppTLVType, acl::DvppChannelDescTLVParam>::const_iterator it =
                channelDesc->tlvParamMap.find(DVPP_CSC_MATRIX);
            if (it == channelDesc->tlvParamMap.cend()) {
                DvppChannelDescTLVParam vdecTLVParam;
                std::shared_ptr<aicpu::dvpp::DvppCscMatrixConfig> const dvppCscMatrixConfig =
                    std::make_shared<aicpu::dvpp::DvppCscMatrixConfig>();
                ACL_REQUIRES_NOT_NULL(dvppCscMatrixConfig);
                dvppCscMatrixConfig->cscMatrix = static_cast<uint32_t>(matrixFormat);
                vdecTLVParam.value = static_cast<std::shared_ptr<void>>(dvppCscMatrixConfig);
                vdecTLVParam.valueLen = sizeof(aicpu::dvpp::DvppCscMatrixConfig);
                channelDesc->tlvParamMap[DVPP_CSC_MATRIX] = vdecTLVParam;
            } else {
                aicpu::dvpp::DvppCscMatrixConfig *const dvppCscMatrixConfig =
                    static_cast<aicpu::dvpp::DvppCscMatrixConfig *>(it->second.value.get());
                ACL_REQUIRES_NOT_NULL(dvppCscMatrixConfig);
                dvppCscMatrixConfig->cscMatrix = static_cast<uint32_t>(matrixFormat);
            }
        }
        ACL_LOG_DEBUG("successfully execute acldvppSetChannelDescMatrix, cscMatrixType = %u",
            static_cast<uint32_t>(matrixFormat));
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::acldvppGetChannelDescHeight(const acldvppChannelDesc *const channelDesc,
        uint32_t &height) const
    {
        ACL_LOG_INFO("start to execute acldvppGetChannelDescHeight");
        if ((channelDesc == nullptr) || (channelDesc->dvppDesc.extendInfo == nullptr)) {
            ACL_LOG_ERROR("[Check][ChannelDesc]channelDesc is null.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"channelDesc or extendInfo"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                argList, argVal, 1U);
            return ACL_ERROR_INVALID_PARAM;
        }
        {
            std::mutex &mutexMap = const_cast<std::mutex &>(channelDesc->mutexForTLVMap);
            const std::unique_lock<std::mutex> lk{mutexMap};
            const auto &it = channelDesc->tlvParamMap.find(DVPP_HEIGHT_JPEGE);
            if (it == channelDesc->tlvParamMap.end()) {
                height = JPEGE_MAX_HEIGHT;
                ACL_LOG_INFO("get default height, height = %u", height);
                return ACL_SUCCESS;
            }

            aicpu::dvpp::DvppChannelHeightConfig *const heightConfig =
                static_cast<aicpu::dvpp::DvppChannelHeightConfig *>(it->second.value.get());
            ACL_REQUIRES_NOT_NULL(heightConfig);
            height = heightConfig->height;
            ACL_LOG_INFO("successfully execute acldvppGetChannelDescHeight, height = %u", height);
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::acldvppGetChannelDescWidth(const acldvppChannelDesc *const channelDesc,
        uint32_t &width) const
    {
        ACL_LOG_INFO("start to execute acldvppGetChannelDescWidth");
        if ((channelDesc == nullptr) || (channelDesc->dvppDesc.extendInfo == nullptr)) {
            ACL_LOG_ERROR("[Check][ChannelDesc]channelDesc is null.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"channelDesc or extendInfo"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                argList, argVal, 1U);
            return ACL_ERROR_INVALID_PARAM;
        }
        {
            std::mutex &mutexMap = const_cast<std::mutex &>(channelDesc->mutexForTLVMap);
            const std::unique_lock<std::mutex> lk{mutexMap};
            const auto &it = channelDesc->tlvParamMap.find(DVPP_WIDTH_JPEGE);
            if (it == channelDesc->tlvParamMap.end()) {
                width = JPEGE_MAX_WIDTH;
                ACL_LOG_INFO("get default width, width = %u", width);
                return ACL_SUCCESS;
            }

            aicpu::dvpp::DvppChannelWidthConfig *const widthConfig =
                static_cast<aicpu::dvpp::DvppChannelWidthConfig *>(it->second.value.get());
            ACL_REQUIRES_NOT_NULL(widthConfig);
            width = widthConfig->width;
            ACL_LOG_INFO("successfully execute acldvppGetChannelDescWidth, width = %u", width);
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::acldvppSetChannelDescHeight(acldvppChannelDesc *const channelDesc,
        const uint32_t height) const
    {
        ACL_LOG_INFO("start to execute acldvppSetChannelDescHeight");
        if ((channelDesc == nullptr) || (channelDesc->dvppDesc.extendInfo == nullptr)) {
            ACL_LOG_ERROR("[Check][ChannelDesc]channelDesc is null.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"channelDesc or extendInfo"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                argList, argVal, 1U);
            return ACL_ERROR_INVALID_PARAM;
        }
        // check height whether or not larger than max resolution ratio
        if (height > JPEGE_MAX_HEIGHT) {
            ACL_LOG_ERROR("[Check][matrixFormat]input height[%u] is larger than max resolution ratio[8192]", height);
            const std::string heightFormatStr = std::to_string(height);
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"height", heightFormatStr.c_str(), "is larger than max resolution ratio[8192]"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                argList, argVal, 3U);
            return ACL_ERROR_INVALID_PARAM;
        }

        {
            const std::unique_lock<std::mutex> lk{channelDesc->mutexForTLVMap};
            std::map<acl::DvppTLVType, acl::DvppChannelDescTLVParam>::const_iterator it =
                channelDesc->tlvParamMap.find(DVPP_HEIGHT_JPEGE);
            if (it == channelDesc->tlvParamMap.cend()) {
                DvppChannelDescTLVParam channelTLVParam;
                std::shared_ptr<aicpu::dvpp::DvppChannelHeightConfig> const heightConfig =
                    std::make_shared<aicpu::dvpp::DvppChannelHeightConfig>();
                ACL_REQUIRES_NOT_NULL(heightConfig);
                heightConfig->height = height;
                channelTLVParam.value = static_cast<std::shared_ptr<void>>(heightConfig);
                channelTLVParam.valueLen = sizeof(aicpu::dvpp::DvppChannelHeightConfig);
                channelDesc->tlvParamMap[DVPP_HEIGHT_JPEGE] = channelTLVParam;
            } else {
                aicpu::dvpp::DvppChannelHeightConfig *const heightConfig =
                    static_cast<aicpu::dvpp::DvppChannelHeightConfig *>(it->second.value.get());
                ACL_REQUIRES_NOT_NULL(heightConfig);
                heightConfig->height = height;
            }
        }
        ACL_LOG_INFO("successfully execute acldvppSetChannelDescHeight, height = %u", height);
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::DvppMallocInternal(void **const tmpData, const uint64_t tmpDataSize) const
    {
        const rtError_t rtRet = rtDvppMallocWithFlag(tmpData, tmpDataSize,
            static_cast<uint32_t>(RT_MEMORY_ATTRIBUTE_READONLY));
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Alloc][Mem]alloc device memory for channel tmp buffer failed, "
                "size = %zu, runtime errorCode = %d", tmpDataSize, rtRet);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }

        ACL_LOG_INFO("execute DvppMallocInternal success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::acldvppSetChannelCmdlistReadOnly(acldvppChannelDesc *const channelDesc,
        const uint32_t readOnly) const
    {
        ACL_LOG_INFO("start to execute acldvppSetChannelCmdlistReadOnly");
        {
            DvppChannelDescTLVParam channelTLVParam;
            std::mutex &mutexMap = const_cast<std::mutex &>(channelDesc->mutexForTLVMap);
            const std::unique_lock<std::mutex> lk{mutexMap};
            std::shared_ptr<aicpu::dvpp::DvppChannelCmdlistConfig> const cmdlistConfig =
                std::make_shared<aicpu::dvpp::DvppChannelCmdlistConfig>();
            ACL_REQUIRES_NOT_NULL(cmdlistConfig);
            cmdlistConfig->readOnly = readOnly;
            channelTLVParam.value = static_cast<std::shared_ptr<void>>(cmdlistConfig);
            channelTLVParam.valueLen = sizeof(aicpu::dvpp::DvppChannelCmdlistConfig);
            channelDesc->tlvParamMap[DVPP_CMDLIST_READONLY] = channelTLVParam;
        }
        ACL_LOG_INFO("successfully execute acldvppSetChannelCmdlistReadOnly, readonly = %u", readOnly);
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::acldvppSetChannelDescWidth(acldvppChannelDesc *const channelDesc,
        const uint32_t width) const
    {
        ACL_LOG_INFO("start to execute acldvppSetChannelDescWidth");
        if ((channelDesc == nullptr) || (channelDesc->dvppDesc.extendInfo == nullptr)) {
            ACL_LOG_ERROR("[Check][ChannelDesc]channelDesc is null.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"channelDesc or extendInfo"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                argList, argVal, 1U);
            return ACL_ERROR_INVALID_PARAM;
        }
        // check width whether or not larger than max resolution ratio
        if (width > JPEGE_MAX_WIDTH) {
            ACL_LOG_ERROR("[Check][matrixFormat]input width[%u] is larger than max resolution ratio[8192]", width);
            const std::string widthFormatStr = std::to_string(width);
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"width", widthFormatStr.c_str(), "is larger than max resolution ratio[8192]"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                argList, argVal, 3U);
            return ACL_ERROR_INVALID_PARAM;
        }

        {
            const std::unique_lock<std::mutex> lk{channelDesc->mutexForTLVMap};
            std::map<acl::DvppTLVType, acl::DvppChannelDescTLVParam>::const_iterator it =
                channelDesc->tlvParamMap.find(DVPP_WIDTH_JPEGE);
            if (it == channelDesc->tlvParamMap.cend()) {
                DvppChannelDescTLVParam channelTLVParam;
                std::shared_ptr<aicpu::dvpp::DvppChannelWidthConfig> const widthConfig =
                    std::make_shared<aicpu::dvpp::DvppChannelWidthConfig>();
                ACL_REQUIRES_NOT_NULL(widthConfig);
                widthConfig->width = width;
                channelTLVParam.value = static_cast<std::shared_ptr<void>>(widthConfig);
                channelTLVParam.valueLen = sizeof(aicpu::dvpp::DvppChannelWidthConfig);
                channelDesc->tlvParamMap[DVPP_WIDTH_JPEGE] = channelTLVParam;
            } else {
                aicpu::dvpp::DvppChannelWidthConfig *const widthConfig =
                    static_cast<aicpu::dvpp::DvppChannelWidthConfig *>(it->second.value.get());
                ACL_REQUIRES_NOT_NULL(widthConfig);
                widthConfig->width = width;
            }
        }
        ACL_LOG_INFO("successfully execute acldvppSetChannelDescWidth, width = %u", width);
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::ValidEqualizeHistParam(const acldvppPicDesc *const inputDesc,
                                                        const acldvppPicDesc *const outputDesc) const
    {
        // check vpc input format
        const aclError validFormatRet = ValidateEqualizeHistFormat(
            static_cast<acldvppPixelFormat>(inputDesc->dvppPicDesc.format));
        if (validFormatRet != ACL_SUCCESS) {
            ACL_LOG_ERROR("[Validate][EqualizeHistFormat]input acldvppPicDesc format verify failed, "
                "result = %d, format = %u.", validFormatRet, inputDesc->dvppPicDesc.format);
            const std::string convertedStr = std::to_string(inputDesc->dvppPicDesc.format);
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"HistFormat", convertedStr.c_str(), "not set in range"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                argList, argVal, 3U);
            return validFormatRet;
        }
        // check vpc output foramt
        if (inputDesc->dvppPicDesc.format != outputDesc->dvppPicDesc.format) {
            ACL_LOG_ERROR("[Check][Format]output format must match input format, "
                "but got input format = %u, output format = %u.",
                inputDesc->dvppPicDesc.format, outputDesc->dvppPicDesc.format);
            const std::string convertedStr = std::to_string(outputDesc->dvppPicDesc.format);
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"output format", convertedStr.c_str(),
                "must match input format"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                argList, argVal, 3U);
            return ACL_ERROR_INVALID_PARAM;
        }

        const uint32_t srcWidth = inputDesc->dvppPicDesc.width;
        const uint32_t srcHeight = inputDesc->dvppPicDesc.height;
        const uint32_t srcWidthStride = inputDesc->dvppPicDesc.widthStride;
        const uint32_t srcHeightStride = inputDesc->dvppPicDesc.heightStride;
        const uint32_t dstWidth = outputDesc->dvppPicDesc.width;
        const uint32_t dstHeight = outputDesc->dvppPicDesc.height;
        const uint32_t dstWidthStride = outputDesc->dvppPicDesc.widthStride;
        const uint32_t dstHeightStride = outputDesc->dvppPicDesc.heightStride;
        const bool validPicParam = (srcWidth != dstWidth) || (srcHeight != dstHeight) ||
                             (srcWidthStride != dstWidthStride) || (srcHeightStride != dstHeightStride);
        if (validPicParam) {
            ACL_LOG_ERROR("[Check][validPicParam]equalize hist input param must match output, "
                "but got srcWidth = %u, srcHeight = %u, "
                "srcWidthStride = %u, srcHeightStride = %u, dstWidth = %u dstHeight = %u, "
                "dstWidthStride = %u, dstHeightStride = %u", srcWidth, srcHeight, srcWidthStride,
                srcHeightStride, dstWidth, dstHeight, dstWidthStride, dstHeightStride);
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"input params", "",
                "equalize hist input param must match output"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                argList, argVal, 3U);
            return ACL_ERROR_INVALID_PARAM;
        }

        return ACL_SUCCESS;
    }

    acldvppLutMap *ImageProcessorV200::acldvppCreateLutMap() const
    {
        ACL_LOG_INFO("start to execute acldvppCreateLutMap");
        acldvppLutMap *aclLutMap = nullptr;
        // alloc memory
        const uint32_t acldvppLutMapSize = acl::dvpp::CalAclDvppStructSize(aclLutMap);
        void *structAddr = malloc(static_cast<size_t>(acldvppLutMapSize));
        if (structAddr == nullptr) {
            ACL_LOG_INNER_ERROR("[Malloc][Mem]malloc acldvppLutMap struct memory failed. "
                "size is %u.", acldvppLutMapSize);
            return nullptr;
        }

        // create acldvppLutMap in memory
        aclLutMap = new (structAddr)acldvppLutMap();
        if (aclLutMap == nullptr) {
            ACL_LOG_INNER_ERROR("[Malloc][LutMap]create acldvppLutMap with function new failed.");
            ACL_FREE(structAddr);
            return nullptr;
        }

        // fill value
        for (uint32_t idx = 0U; idx < aclLutMap->dvppLutMap.dims; ++idx) {
            aclLutMap->dvppLutMap.lens[idx] = LUT_MAP_DEFAULT_VALUE;
        }
        const size_t mapSize = static_cast<size_t>(aclLutMap->dvppLutMap.dims) *
            static_cast<size_t>(LUT_MAP_DEFAULT_VALUE);
        uint8_t *const mapAddr = new (std::nothrow)uint8_t[mapSize];
        if (mapAddr == nullptr) {
            ACL_LOG_INNER_ERROR("[Malloc][Mem]malloc acldvppLutMap map memory failed. size is %zu.", mapSize);
            ACL_FREE(structAddr);
            return nullptr;
        }

        aclLutMap->dvppLutMap.map = mapAddr;
        return aclLutMap;
    }

    aclError ImageProcessorV200::acldvppDestroyLutMap(acldvppLutMap *lutMap) const
    {
        if (lutMap != nullptr) {
            ACL_DELETE_ARRAY_AND_SET_NULL(lutMap->dvppLutMap.map);
            ACL_FREE(lutMap);
        }
        return ACL_SUCCESS;
    }

    uint32_t ImageProcessorV200::acldvppGetLutMapDims(const acldvppLutMap *const lutMap) const
    {
        if (lutMap == nullptr) {
            ACL_LOG_ERROR("[Check][LutMap]param lutMap is nullptr.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"lutMap"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                argList, argVal, 1U);
            return 0U;
        }
        return static_cast<uint32_t>(lutMap->dvppLutMap.dims);
    }

    aclError ImageProcessorV200::acldvppGetLutMapData(const acldvppLutMap *const lutMap,
                                                      const uint32_t dim,
                                                      uint8_t **const data,
                                                      uint32_t *const len) const
    {
        ACL_REQUIRES_NOT_NULL(lutMap);
        ACL_REQUIRES_NOT_NULL(lutMap->dvppLutMap.map);
        if (dim >= lutMap->dvppLutMap.dims) {
            ACL_LOG_INNER_ERROR("[Check][Dims]dim[%u] should be smaller than dvppLutMap dims[%u]",
                dim, static_cast<uint32_t>(lutMap->dvppLutMap.dims));
            return ACL_ERROR_INVALID_PARAM;
        }

        uint32_t dataSize = 0U;
        for (uint32_t idx = 0U; idx < dim; ++idx) {
            dataSize += lutMap->dvppLutMap.lens[idx];
        }
        *len = static_cast<uint32_t>(lutMap->dvppLutMap.lens[dim]);
        *data = reinterpret_cast<uint8_t *>(reinterpret_cast<uintptr_t>(lutMap->dvppLutMap.map) + dataSize);
        return ACL_SUCCESS;
    }

    acldvppBorderConfig *ImageProcessorV200::acldvppCreateBorderConfig() const
    {
        ACL_LOG_INFO("start to execute acldvppCreateBorderConfig");
        acldvppBorderConfig *aclBorderConfig = nullptr;
        // alloc memory
        const uint32_t acldvppLutMapSize = acl::dvpp::CalAclDvppStructSize(aclBorderConfig);
        void *structAddr = malloc(static_cast<size_t>(acldvppLutMapSize));
        if (structAddr == nullptr) {
            ACL_LOG_INNER_ERROR("[Malloc][Mem]malloc acldvppBorderConfig struct memory failed. "
                "size is %u.", acldvppLutMapSize);
            return nullptr;
        }

        // create acldvppLutMap in memory
        aclBorderConfig = new (structAddr)acldvppBorderConfig();
        if (aclBorderConfig == nullptr) {
            ACL_LOG_INNER_ERROR("[Malloc][BorderConfig]create acldvppBorderConfig with function new failed.");
            ACL_FREE(structAddr);
            return nullptr;
        }

        return aclBorderConfig;
    }

    aclError ImageProcessorV200::acldvppDestroyBorderConfig(acldvppBorderConfig *const borderConfig) const
    {
        if (borderConfig != nullptr) {
            free(borderConfig);
        }
        return ACL_SUCCESS;
    }

    void ImageProcessorV200::SetDvppWaitTaskType(acldvppChannelDesc *const channelDesc) const
    {
        channelDesc->dvppWaitTaskType = EVENT_TASK;
        ACL_LOG_INFO("dvpp wait task type is event.");
    }

    size_t ImageProcessorV200::GetCmdlistBuffSize() const
    {
        return acl::dvpp::DVPP_CMDLIST_BUFFER_SIZE_V200;
    }

    aclError ImageProcessorV200::SetCscMatrixForCompatibility(acldvppChannelDesc *const channelDesc) const
    {
        if ((channelDesc->dvppDesc.channelMode & (static_cast<uint32_t>(DVPP_CHNMODE_VPC))) == 0U) {
            return ACL_SUCCESS;
        }
        ACL_LOG_DEBUG("need set csc matrix param in v200 vpc channel for compatibility");
        const uint32_t currentOffset = channelDesc->dvppDesc.len;
        const aicpu::dvpp::DvppCscMatrixConfig tmpCscMatrix;
        uint32_t tmpOffset = currentOffset;
        ACL_CHECK_ASSIGN_UINT32T_ADD(tmpOffset, sizeof(tmpCscMatrix), tmpOffset);
        if (tmpOffset > DVPP_CHANNEL_DESC_TLV_LEN) {
            ACL_LOG_INNER_ERROR("[Check][Offset] offset %u can not be larger than %u",
                tmpOffset, DVPP_CHANNEL_DESC_TLV_LEN);
            return ACL_ERROR_FAILURE;
        }
        const auto ret = memcpy_s(channelDesc->dvppDesc.extendInfo + currentOffset, sizeof(tmpCscMatrix),
            &tmpCscMatrix, sizeof(tmpCscMatrix));
        if (ret != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][Mem]call memcpy_s failed, result = %d, srcLen = %zu, dstLen = %zu", ret,
                sizeof(tmpCscMatrix), sizeof(tmpCscMatrix));
            return ACL_ERROR_FAILURE;
        }
        channelDesc->dvppDesc.len = currentOffset + static_cast<uint32_t>(sizeof(tmpCscMatrix));
        return ACL_SUCCESS;
    }

    aclError ImageProcessorV200::ValidateJpegOutputFormat(const acldvppPixelFormat format)
    {
        static const std::set<acldvppPixelFormat> jpegOutputFormatSet = {
            acldvppPixelFormat::PIXEL_FORMAT_YUV_400,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_422,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_444,
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_440,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_440,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_444,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_422,
            acldvppPixelFormat::PIXEL_FORMAT_UNKNOWN
        };

        std::set<acldvppPixelFormat>::const_iterator iter = jpegOutputFormatSet.find(format);
        if (iter != jpegOutputFormatSet.cend()) {
            return ACL_SUCCESS;
        }
        return ACL_ERROR_FORMAT_NOT_MATCH;
    }
    }
}
